package com.ruoyi.teaching.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.constant.HttpStatus;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.li.work.mapper.SysUserMapper;
import com.ruoyi.li.work.mapper.SysUserRoleMapper;
import com.ruoyi.teaching.domain.*;
import com.ruoyi.teaching.domain.vo.PlatformCCourseVO;
import com.ruoyi.teaching.domain.vo.PlatformEEventVO;
import com.ruoyi.teaching.mapper.PlatformEEventApplyMapper;
import com.ruoyi.teaching.mapper.PlatformEEventMapper;
import com.ruoyi.teaching.mapper.PlatformEEventResultMapper;
import com.ruoyi.teaching.service.PlatformEEventService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.teaching.utils.UniversalUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author 王旭
 * @since 2025-03-03
 */
@Service
public class PlatformEEventServiceImpl extends ServiceImpl<PlatformEEventMapper, PlatformEEvent> implements PlatformEEventService {
    @Autowired
    private PlatformEEventMapper platformEEventMapper;
    @Autowired
    private PlatformEEventApplyMapper eventApplyMapper;
    @Autowired
    private SysUserMapper userMapper;
    @Autowired
    private SysUserRoleMapper sysUserRoleMapper;
    @Autowired
    private PlatformEEventResultMapper eventResultMapper;
    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public AjaxResult addEvent(PlatformEEvent platformEEvent) {
        UniversalCreateUpdate createUpdate = UniversalUtil.getCreateUpdate(userMapper);
        platformEEvent.setCreateBy(createUpdate.getName());
        platformEEvent.setCreateTime(DateUtils.getNowDate());
        platformEEvent.setCreateId(createUpdate.getId());
        int insert = platformEEventMapper.insert(platformEEvent);
        if (insert > 0) {
            return new AjaxResult(HttpStatus.SUCCESS, "添加成功");
        } else {
            return new AjaxResult(HttpStatus.ERROR, "添加失败");
        }
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public AjaxResult deleteEvent(Long[] ids) {
        for (Long id : ids) {
            int i1 = platformEEventMapper.deleteById(id);
            if (i1 > 0) {
                QueryWrapper<PlatformEEventApply> platformEEventApplyQueryWrapper = new QueryWrapper<>();
                platformEEventApplyQueryWrapper.eq("event_id", id);
                eventApplyMapper.delete(platformEEventApplyQueryWrapper);
            } else {
                throw new RuntimeException("删除失败");
            }
        }
        return new AjaxResult(HttpStatus.SUCCESS, "删除成功");
    }

    /**
     * @param pageNum
     * @param pageSize
     * @param eventName
     * @param eventStatus            0未开始1报名中2报名截止
     * @param eventLevel
     * @param professionalCategoryId
     * @return
     */
    @Override
    public AjaxResult queryEventSignUp(Integer pageNum, Integer pageSize, String eventName, Integer eventStatus, Integer eventLevel, Integer professionalCategoryId) {

        int roleId = 0;
        Long userId = SecurityUtils.getUserId();
        if (userId != null) {
            roleId = Math.toIntExact(sysUserRoleMapper.selectRoleIdbyUserId(userId)[0]);
        }
        if (roleId != 2 && roleId != 6 && roleId != 1) {
            return new AjaxResult(HttpStatus.ERROR, "当前角色暂无权限");
        }
        QueryWrapper<PlatformEEvent> platformEEventQueryWrapper = new QueryWrapper<>();
        Page<PlatformEEvent> platformEEventPage = new Page<>(pageNum, pageSize);
        if (null != eventName && !eventName.equals("")) {
            platformEEventQueryWrapper.like("event_name", eventName);
        }
        // 处理赛事状态条件筛选
        if (eventStatus != null) {
            LocalDateTime now = LocalDateTime.now(ZoneId.of("Asia/Shanghai"));
            if (eventStatus == 0) { // 未开始
                platformEEventQueryWrapper.ge("apply_start_time", now);
            } else if (eventStatus == 1) { // 报名中
                platformEEventQueryWrapper.le("apply_start_time", now).ge("apply_end_time", now);
            } else if (eventStatus == 2) { // 报名截止
                platformEEventQueryWrapper.lt("apply_end_time", now);
            }
        }
        if (null != eventLevel) {
            platformEEventQueryWrapper.eq("event_level", eventLevel);
        }
        if (null != professionalCategoryId) {
            platformEEventQueryWrapper.eq("professional_category_id", professionalCategoryId);
        }
        if (roleId == 2) {
            platformEEventQueryWrapper.eq("create_id", userId);
        }
        platformEEventQueryWrapper.orderByDesc("create_time");
        platformEEventPage = platformEEventMapper.selectPage(platformEEventPage, platformEEventQueryWrapper);
        Page<PlatformEEventVO> platformEEventVOPage = new Page<>(pageNum, pageSize);
        BeanUtils.copyProperties(platformEEventPage, platformEEventVOPage);
        List<PlatformEEventVO> platformEEventVOS = new ArrayList<>();
        for (PlatformEEvent record : platformEEventPage.getRecords()) {
            PlatformEEventVO platformEEventVO = new PlatformEEventVO();
            BeanUtils.copyProperties(record, platformEEventVO);
            setEventStatusUtil(platformEEventVO); // 设置赛事状态
            platformEEventVOS.add(platformEEventVO);
        }
        platformEEventVOPage.setRecords(platformEEventVOS);
        return new AjaxResult(HttpStatus.SUCCESS, "查询成功", platformEEventVOPage);
    }

    private final ConcurrentHashMap<Long, Lock> lockMap = new ConcurrentHashMap<>();

    @Override
    public AjaxResult addBrowseCount(Long id) {
        Lock lock = lockMap.computeIfAbsent(id, k -> new ReentrantLock());
        lock.lock();
        try {
            PlatformEEvent platformEEvent = platformEEventMapper.selectById(id);
            if (platformEEvent != null) {
                int count = platformEEvent.getLookNum() + 1;
                platformEEvent.setLookNum(count);
                int i = platformEEventMapper.updateById(platformEEvent);
                if (i > 0) {
                    return new AjaxResult(HttpStatus.SUCCESS, "浏览数加一成功");
                } else {
                    return new AjaxResult(HttpStatus.ERROR, "浏览数加一失败");
                }
            }
            return new AjaxResult(HttpStatus.SUCCESS, "该事件不存在");
        } finally {
            lock.unlock();
            lockMap.remove(id, lock);
        }
    }

    /**
     * 查询赛事列表
     *
     * @param pageNum                当前页码
     * @param pageSize               每页显示条数
     * @param eventName              赛事名称（模糊查询）
     * @param eventStatus            赛事状态（0未开始，1报名中，2报名截止，3结果公示，999全部）
     * @param eventLevel             赛事等级（999表示查询全部）
     * @param professionalCategoryId 专业大类 ID（999表示查询全部）
     * @param professionalId         专业分类 ID（999表示查询全部）
     * @param sort                   排序方式（0最热，1最新）
     * @return AjaxResult            返回查询结果
     */
    @Override
    public AjaxResult queryEventList(Integer pageNum, Integer pageSize, String eventName, Integer eventStatus, Integer eventLevel, Integer professionalCategoryId, Integer professionalId, Integer sort) {
        List<PlatformEEventVO> returnResult = new ArrayList<>();

        // 查询赛事结果表（已结束赛事，状态固定为3：结果公示）
        QueryWrapper<PlatformEEventResult> eventResultQueryWrapper = new QueryWrapper<>();
        if (eventName != null && !eventName.isEmpty()) {
            eventResultQueryWrapper.like("event_name", eventName);
        }
        if (eventLevel != null && eventLevel != 999) {
            eventResultQueryWrapper.eq("event_level", eventLevel);
        }
        if (professionalCategoryId != null && professionalCategoryId != 999) {
            eventResultQueryWrapper.eq("professional_category_id", professionalCategoryId);
        }
        if (professionalId != null && professionalId != 999) {
            eventResultQueryWrapper.eq("professional_id", professionalId);
        }

        List<PlatformEEventResult> eventResultList = eventResultMapper.selectList(eventResultQueryWrapper);
        for (PlatformEEventResult eventResult : eventResultList) {
            PlatformEEventVO PlatformEEventVO = new PlatformEEventVO();
            BeanUtils.copyProperties(eventResult, PlatformEEventVO);
            PlatformEEventVO.setEventStatus(3); // 结果公示
            if (eventStatus == null || eventStatus == 999 || eventStatus == 3) {
                returnResult.add(PlatformEEventVO);
            }
        }


        // 如果只查询结果公示赛事，则直接返回
        if (eventStatus != null && eventStatus == 3) {
            return new AjaxResult(HttpStatus.SUCCESS, "查询成功", toPage(returnResult, pageNum, pageSize, sort));
        }

        // 查询比赛表（未结束赛事）
        QueryWrapper<PlatformEEvent> eventQueryWrapper = new QueryWrapper<>();
        if (eventName != null && !eventName.isEmpty()) {
            eventQueryWrapper.like("event_name", eventName);
        }
        if (eventLevel != null && eventLevel != 999) {
            eventQueryWrapper.eq("event_level", eventLevel);
        }
        if (professionalCategoryId != null && professionalCategoryId != 999) {
            eventQueryWrapper.eq("professional_category_id", professionalCategoryId);
        }
        if (professionalId != null && professionalId != 999) {
            eventQueryWrapper.eq("professional_id", professionalId);
        }

        // 处理赛事状态条件筛选
        if (eventStatus != null && eventStatus != 999) {
            LocalDateTime now = LocalDateTime.now(ZoneId.of("Asia/Shanghai"));
            if (eventStatus == 0) { // 未开始
                eventQueryWrapper.ge("apply_start_time", now);
            } else if (eventStatus == 1) { // 报名中
                eventQueryWrapper.le("apply_start_time", now).ge("apply_end_time", now);
            } else if (eventStatus == 2) { // 报名截止
                eventQueryWrapper.lt("apply_end_time", now);
            }
        }


        List<PlatformEEvent> platformEEvents = platformEEventMapper.selectList(eventQueryWrapper);
        for (PlatformEEvent platformEEvent : platformEEvents) {
            PlatformEEventVO platformEEventVO = new PlatformEEventVO();
            BeanUtils.copyProperties(platformEEvent, platformEEventVO);
            setEventStatusUtil(platformEEventVO); // 设置赛事状态
            returnResult.add(platformEEventVO);
        }

        return new AjaxResult(HttpStatus.SUCCESS, "查询成功", toPage(returnResult, pageNum, pageSize, sort));
    }

    /**
     * 设置赛事状态
     *
     * @param PlatformEEventVO 赛事对象
     */
    private void setEventStatusUtil(PlatformEEventVO PlatformEEventVO) {
        String applyStartTime = PlatformEEventVO.getApplyStartTime();
        String applyEndTime = PlatformEEventVO.getApplyEndTime();

        // 获取北京时间
        LocalDateTime now = LocalDateTime.now(ZoneId.of("Asia/Shanghai"));

        try {
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

            LocalDateTime startTime = applyStartTime != null ? LocalDateTime.parse(applyStartTime, formatter) : null;
            LocalDateTime endTime = applyEndTime != null ? LocalDateTime.parse(applyEndTime, formatter) : null;

            if (startTime != null && now.isBefore(startTime)) {
                PlatformEEventVO.setEventStatus(0); // 未开始
            } else if (startTime != null && endTime != null &&
                    (now.isEqual(startTime) || now.isAfter(startTime)) && now.isBefore(endTime)) {
                PlatformEEventVO.setEventStatus(1); // 报名中
            } else if (endTime != null && now.isAfter(endTime)) {
                PlatformEEventVO.setEventStatus(2); // 报名截止
            }

        } catch (DateTimeParseException e) {
            PlatformEEventVO.setEventStatus(-1); // 如果时间格式有问题，标记为异常状态
            e.printStackTrace(); // 打印异常日志，方便排查
        }
    }


    @Override
    public AjaxResult getEventInfoById(Long id) {
        PlatformEEvent platformEEvent = platformEEventMapper.selectById(id);
        return new AjaxResult(HttpStatus.SUCCESS, "查询成功", platformEEvent);
    }

    @Override
    public AjaxResult selectArea() {
        List<String> area = redisTemplate.opsForList().range("area", 0, -1);
        return  new AjaxResult(HttpStatus.SUCCESS,"操作成功",area);
    }

    private Page<PlatformEEventVO> toPage(List<PlatformEEventVO> eEventFrontVOS, Integer pageNum, Integer pageSize, Integer sortord) {

        // 排序逻辑
        if (sortord != null && sortord == 1) {
            // 按最新时间排序
            eEventFrontVOS.sort(Comparator.comparing(PlatformEEventVO::getCreateTime).reversed()
                    .thenComparing(Comparator.comparing(PlatformEEventVO::getLookNum).reversed()));
        } else {
            // 默认按最热排序，再按上传时间排序
            eEventFrontVOS.sort(Comparator.comparing(PlatformEEventVO::getLookNum).reversed()
                    .thenComparing(Comparator.comparing(PlatformEEventVO::getCreateTime).reversed()));
        }

        // 确定分页参数
        int total = eEventFrontVOS.size();
        if (pageNum == null || pageNum < 1) {
            pageNum = 1;
        }
        if (pageSize == null || pageSize < 1) {
            pageSize = 10;
        }
        int start = Math.min((pageNum - 1) * pageSize, total);
        int end = Math.min(start + pageSize, total);

        // 获取当前页的数据
        List<PlatformEEventVO> paginatedList = eEventFrontVOS.subList(start, end);

        // 设置分页信息
        Page<PlatformEEventVO> page = new Page<>(pageNum, pageSize);
        page.setRecords(paginatedList);
        page.setTotal(total);

        return page;
    }
}
